package com.baomidou.springwind.pojo;

import com.baomidou.springwind.entity.NetworkNode;

import java.util.*;

/**
 * Created by demo on 2017/7/15.
 */
public class GroupBuilder {
    private Map<NetworkNode, List<NetworkNode>> groupNodeMap = new LinkedHashMap<NetworkNode, List<NetworkNode>>();
    private Map<NetworkNode, Map<NetworkNode, Long>> nodeMaps = new LinkedHashMap<NetworkNode, Map<NetworkNode, Long>>();

    private long count;

    public GroupBuilder(Map<NetworkNode, Map<NetworkNode, Long>> nodeMaps) {
        this.nodeMaps = nodeMaps;
    }

    public LinkedHashMap<NetworkNode, List<NetworkNode>> build() {
        double max = Double.MAX_VALUE;
        LinkedHashMap<NetworkNode, List<NetworkNode>> groups = null;
        List<NetworkNode> temp = new ArrayList<NetworkNode>();
        for (NetworkNode node : nodeMaps.keySet()) {
            if (canStart(node)) {
                temp.add(node);
            }
        }
        for (NetworkNode head : nodeMaps.keySet()) {
            if (!canStart(head)) {
                continue;
            }
            Set<NetworkNode> remainder = new LinkedHashSet<NetworkNode>(temp);
            remainder.remove(head);
            LinkedHashMap<NetworkNode, List<NetworkNode>> networkNodeListLinkedHashMap = new LinkedHashMap<NetworkNode, List<NetworkNode>>();
            searchGroup(head, remainder, networkNodeListLinkedHashMap);
            double groupBzc = 0;
            for (Map.Entry<NetworkNode, List<NetworkNode>> entry : networkNodeListLinkedHashMap.entrySet()) {
                double q1 = Math.ceil(entry.getKey().getAmount().doubleValue() / 26 / 50);
                double q2 = 0;
                double q3 = 0;
                List<NetworkNode> children = entry.getValue();
                if (children != null) {
                    if (children.size() > 1) {
                        q2 = Math.ceil(children.get(0).getAmount().doubleValue() / 26 / 50);
                    }
                    if (children.size() == 2) {
                        if (children.size() > 1) {
                            q3 = Math.ceil(children.get(1).getAmount().doubleValue() / 26 / 50);
                        }
                    }
                }
                groupBzc += bzc(q1, q2, q3);
            }
            if (groupBzc < max) {
                max = groupBzc;
                groups = networkNodeListLinkedHashMap;
            }
        }
        for (NetworkNode node : nodeMaps.keySet()) {
            if (!canStart(node)) {
                groups.put(node, new ArrayList<NetworkNode>());
            }
        }
        return groups;
//        System.out.println(groups);
    }

    private void searchGroup(NetworkNode node, Set<NetworkNode> remainder, Map<NetworkNode, List<NetworkNode>> groupNodeMap) {
        if (remainder.size() == 0) {
            groupNodeMap.put(node, new ArrayList<NetworkNode>(2));
            System.out.println(groupNodeMap);
            return;
        }
        TreeMap<NetworkNode, Long> distanceMap = (TreeMap<NetworkNode, Long>) nodeMaps.get(node);
        Map.Entry<NetworkNode, Long> temp = null;
        for (Map.Entry<NetworkNode, Long> entry : distanceMap.entrySet()) {
            if (remainder.contains(entry.getKey())) {
                temp = entry;
                break;
            }
        }
        if (temp == null) {
            return;
        }
        Long distance = temp.getValue();
        List<NetworkNode> growpNode = new ArrayList<NetworkNode>(2);
        groupNodeMap.put(node, growpNode);
        if (distance <= 15000) {
            remainder.remove(temp.getKey());
            growpNode.add(temp.getKey());
        }

        for (Map.Entry<NetworkNode, Long> entry : distanceMap.entrySet()) {
            if (remainder.contains(entry.getKey())) {
                temp = entry;
                break;
            }
        }
        if (temp != null) {
            distance = distance + temp.getValue();
            if (distance <= 20000) {
                remainder.remove(temp.getKey());
                growpNode.add(temp.getKey());
            }
        }
        if(remainder.size() == 0){
            return;
        }
        List<NetworkNode> nodeList = new ArrayList<NetworkNode>(remainder);
        NetworkNode startNode = nodeList.get(0);
//        int j = 0;
//        for (int i = 0; i < nodeList.size(); i++) {
//            if (canStart(nodeList.get(i))) {
//                startNode = nodeList.get(i);
//                j = i;
//                break;
//            }
//        }
        remainder.remove(nodeList.get(0));
        searchGroup(startNode, remainder, groupNodeMap);
//        for (NetworkNode node1 : remainder) {
//            if (canStart(node1)) {
//                Set<NetworkNode> tempSet = new HashSet<NetworkNode>(remainder);
//                tempSet.remove(node1);
//                searchGroup(node1, tempSet, new LinkedHashMap<NetworkNode, List<NetworkNode>>(groupNodeMap));
//            }
//        }
    }

    /**
     * 医院料架数大于4小于8
     * 料架数=订单量/22/550
     */
    private boolean canStart(NetworkNode node) {
        double amout = node.getAmount().doubleValue();
        double shelf = Math.ceil(amout / 22 / 550);
        return shelf >= 0 && shelf <= 30;
    }

    private double bzc(double q1, double q2, double q3) {
        return Math.pow(Math.pow(q1 - (q1 + q2 + q3 / 3), 2d) + Math.pow(q2 - (q1 + q2 + q3 / 3), 2) + Math.pow(q3 - (q1 + q2 + q3 / 3), 2d), 0.5);
    }
}
